﻿#pragma once
#include <queue>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <atomic>
#include <chrono>
#include "RejectPolicy.h"
using Task = std::function<void()>;

class BlockingQueue {
public:

	explicit BlockingQueue() = default;
	explicit BlockingQueue(RejectPolicy policy) : rejectPolicy_(policy) {}
    virtual ~BlockingQueue() = default;

    BlockingQueue(const BlockingQueue&) = delete;
    BlockingQueue& operator=(const BlockingQueue&) = delete;

	virtual void push(Task task) = 0;
    virtual Task take() = 0;
    virtual Task takeFor(std::chrono::microseconds ms) = 0;
    virtual bool isEmpty() = 0;
	virtual bool isFull() = 0;
    virtual void stop() = 0; 
    virtual size_t size() = 0;
	virtual size_t capacity() const = 0;

protected:
	std::mutex mutex_;// protects the queue
	std::condition_variable cond_;// notifies a waiting thread
    std::atomic<bool> running_{true};
    std::atomic<size_t> cachedSize_{ 0 };// 用于缓存队列大小，减少锁的使用
    void incr() { cachedSize_.fetch_add(1); }
    void decr() { cachedSize_.fetch_sub(1); }
	size_t cached() const { return cachedSize_.load(); }
    RejectPolicy rejectPolicy_{RejectPolicy::CallerRuns};
};